package org.lboot.flow.custom.eda.provider;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.lboot.flow.constant.FlowNodeTypeConst;
import org.lboot.flow.custom.eda.node.*;
import org.lboot.flow.model.node.*;
import org.lboot.flow.parser.FlowParser;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
@AllArgsConstructor
public class EventFlowParser implements FlowParser {
    @Override
    public String type() {
        return "EDA";
    }

    @Override
    public List<BaseModel> parser(String define) {
        // 构建
        NodeConfig config = buildNode(define);
        return covert(config);
    }

    public List<BaseModel> covert(NodeConfig config) {
        List<BaseModel> models = new ArrayList<>();
        if (Validator.isEmpty(config)){
            return new ArrayList<>();
        }
        String type = config.getType();
        if (type.equals(FlowNodeTypeConst.START_NODE)){
            StartModel model = new StartModel();
            BeanUtil.copyProperties(config,model);
            model.setNodeType(FlowNodeTypeConst.START_NODE);
            // 字节节点不为空
            if (Validator.isNotEmpty(config.getChildNode())){
                // 获取下节点ID
                model.setNextNodeId(config.getChildNode().getId());
            }else {
                model.setNextNodeId("end");
            }
            models.add(model);
            models.addAll(covert(config.getChildNode()));
            // 构建
            // 添加结束节点
            EndModel endModel = new EndModel();
            endModel.setId("end");
            endModel.setName("结束节点");
            endModel.setNextNodeId(null);
            endModel.setNodeType(FlowNodeTypeConst.END_NODE);
            models.add(endModel);
            return models;

        }else if (type.equals(FlowNodeTypeConst.TASK_NODE)){
            TaskModel model = new TaskModel();
            TaskNodeConfig taskNodeConfig = (TaskNodeConfig) config;
            //log.info(taskNodeConfig.toString());
            BeanUtil.copyProperties(taskNodeConfig,model);
            model.setNodeType(FlowNodeTypeConst.TASK_NODE);
            // 字节节点不为空
            if (Validator.isNotEmpty(config.getChildNode())){
                // 获取下节点ID
                model.setNextNodeId(config.getChildNode().getId());
            }else {
                model.setNextNodeId("end");
            }
            models.add(model);
            models.addAll(covert(config.getChildNode()));
            return models;
        }else if (type.equals(FlowNodeTypeConst.COMMAND_NODE)){
            CommandModel model = new CommandModel();
            CommandNodeConfig nodeConfig = (CommandNodeConfig) config;
            //log.info(taskNodeConfig.toString());
            BeanUtil.copyProperties(nodeConfig,model);
            model.setNodeType(FlowNodeTypeConst.COMMAND_NODE);
            // 字节节点不为空
            if (Validator.isNotEmpty(config.getChildNode())){
                // 获取下节点ID
                model.setNextNodeId(config.getChildNode().getId());
            }else {
                model.setNextNodeId("end");
            }
            models.add(model);
            models.addAll(covert(config.getChildNode()));
            return models;
        }else if (type.equals(FlowNodeTypeConst.DECISION_TASK_NODE)){
            //决策节点
            DecisionTaskModel model = new DecisionTaskModel();
            DecisionTaskNodeConfig nodeConfig = (DecisionTaskNodeConfig) config;
            //log.info(taskNodeConfig.toString());
            BeanUtil.copyProperties(nodeConfig,model);
            model.setNodeType(FlowNodeTypeConst.DECISION_TASK_NODE);
            // 字节节点不为空
            if (Validator.isNotEmpty(config.getChildNode())){
                // 获取下节点ID
                model.setNextNodeId(config.getChildNode().getId());
            }else {
                model.setNextNodeId("end");
            }
            models.add(model);
            models.addAll(covert(config.getChildNode()));
            return models;
        }
        else if (type.equals(FlowNodeTypeConst.EXCLUSIVE_GATEWAY_NODE)){
            ExclusiveGatewayModel model = new ExclusiveGatewayModel();
            // 排他网关节点如何配置
            ExclusiveGatewayNodeConfig nodeConfig = (ExclusiveGatewayNodeConfig) config;
            //log.info(nodeConfig.toString());
            BeanUtil.copyProperties(nodeConfig,model);
            model.setNodeType(FlowNodeTypeConst.EXCLUSIVE_GATEWAY_NODE);
            // 获取条件列表
            List<ConditionNodeConfig> conditionNodeConfigs = nodeConfig.getConditions();
            // 构建
            List<ConditionModel> conditions = new ArrayList<>();
            List<String> nodeIds = new ArrayList<>();
            for (ConditionNodeConfig node: conditionNodeConfigs){
                ConditionModel conditionModel = new ConditionModel();
                //log.info(node.toString());
                BeanUtil.copyProperties(node, conditionModel, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
                // 补充ID
                if (Validator.isNotEmpty(node.getChildNode())){
                    conditionModel.setNextNodeId(node.getChildNode().getId());
                    nodeIds.add(node.getChildNode().getId());
                }else {
                    conditionModel.setNextNodeId("end");
                    nodeIds.add("end");
                }

                conditions.add(conditionModel);
            }
            model.setConditions(conditions);
            model.setNodeIds(nodeIds);
            models.add(model);
            for (NodeConfig node: conditionNodeConfigs){
                if (Validator.isNotEmpty(node.getChildNode())){
                    //log.info(node.getChildNode().toString());
                    // 分支构建
                    models.addAll(covert(node.getChildNode()));
                }
            }
            return models;
        }else if (type.equals(FlowNodeTypeConst.PARALLEL_GATEWAY_NODE)){
            ParallelGatewayModel model = new ParallelGatewayModel();
            // 排他网关节点如何配置
            ParallelGatewayNodeConfig nodeConfig = (ParallelGatewayNodeConfig) config;
            //log.info(nodeConfig.toString());
            BeanUtil.copyProperties(nodeConfig,model);
            model.setNodeType(FlowNodeTypeConst.PARALLEL_GATEWAY_NODE);
            // 获取条件列表
            List<ConditionNodeConfig> conditionNodeConfigs = nodeConfig.getConditions();
            // 构建
            List<ConditionModel> conditions = new ArrayList<>();
            List<String> nodeIds = new ArrayList<>();
            for (ConditionNodeConfig node: conditionNodeConfigs){
                ConditionModel conditionModel = new ConditionModel();
                //log.info(node.toString());
                BeanUtil.copyProperties(node, conditionModel, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
                // 补充ID
                if (Validator.isNotEmpty(node.getChildNode())){
                    conditionModel.setNextNodeId(node.getChildNode().getId());
                    nodeIds.add(node.getChildNode().getId());
                }else {
                    conditionModel.setNextNodeId("end");
                    nodeIds.add("end");
                }

                conditions.add(conditionModel);
            }
            model.setConditions(conditions);
            model.setNodeIds(nodeIds);
            models.add(model);
            for (NodeConfig node: conditionNodeConfigs){
                if (Validator.isNotEmpty(node.getChildNode())){
                    //log.info(node.getChildNode().toString());
                    // 分支构建
                    models.addAll(covert(node.getChildNode()));
                }
            }
            return models;
        }

        return models;
    }

    private ObjectMapper objectMapper = new ObjectMapper();

    @SneakyThrows
    public NodeConfig buildNode(String config) {
        // JSON转化
        JsonNode root = objectMapper.readTree(config);
        if (Validator.isEmpty(config)){
            return null;
        }
        String type = null;
        JsonNode typeNode = root.get("type");
        if (Validator.isNotEmpty(typeNode)){
            type = typeNode.asText();
        }else {
            return null;
        }
        //log.info(type);
        JsonNode childJsonNode = root.get("childNode");
        String childNode = null;
        if (Validator.isNotEmpty(childJsonNode)){
            // 格式化
            childNode = childJsonNode.toPrettyString();
        }
        //log.info(childNode);
        if (type.equals(FlowNodeTypeConst.START_NODE)){
            StartNodeConfig nodeConfig = JSONUtil.toBean(config, StartNodeConfig.class,true);
            nodeConfig.setChildNode(buildNode(childNode));
            return nodeConfig;
        }else if (type.equals(FlowNodeTypeConst.TASK_NODE)){
            TaskNodeConfig nodeConfig = JSONUtil.toBean(config, TaskNodeConfig.class,true);
            nodeConfig.setChildNode(buildNode(childNode));
            return nodeConfig;
        }else if (type.equals(FlowNodeTypeConst.COMMAND_NODE)){
            CommandNodeConfig nodeConfig = JSONUtil.toBean(config,CommandNodeConfig.class,true);
            nodeConfig.setChildNode(buildNode(childNode));
            return nodeConfig;
        }else if (type.equals(FlowNodeTypeConst.DECISION_TASK_NODE)){
            // 决策节点
            DecisionTaskNodeConfig nodeConfig = JSONUtil.toBean(config,DecisionTaskNodeConfig.class,true);
            nodeConfig.setChildNode(buildNode(childNode));
            return nodeConfig;
        }else if (type.equals(FlowNodeTypeConst.CONDITION_NODE)){
            ConditionNodeConfig nodeConfig = JSONUtil.toBean(config,ConditionNodeConfig.class,true);
            nodeConfig.setChildNode(buildNode(childNode));
            return nodeConfig;
        }
        else if (type.equals(FlowNodeTypeConst.PARALLEL_GATEWAY_NODE)){
            // 并行网关 --> 所有的条件都走
            ParallelGatewayNodeConfig nodeConfig = JSONUtil.toBean(config,ParallelGatewayNodeConfig.class,true);
            JsonNode conditionJsonNodes = root.get("conditionNodes");
            List<ConditionNodeConfig> configs = new ArrayList<>();
            if (Validator.isNotEmpty(conditionJsonNodes)){
                if (conditionJsonNodes.isArray()){
                    for (JsonNode conditionJsonNode:conditionJsonNodes){
                        //log.info(conditionJsonNode.toPrettyString());
                        configs.add((ConditionNodeConfig)buildNode(conditionJsonNode.toPrettyString()));
                    }
                }
            }
            nodeConfig.setConditions(configs);
            return nodeConfig;
        }else if (type.equals(FlowNodeTypeConst.EXCLUSIVE_GATEWAY_NODE)){
            ExclusiveGatewayNodeConfig nodeConfig = JSONUtil.toBean(config,ExclusiveGatewayNodeConfig.class,true);
            JsonNode conditionJsonNodes = root.get("conditionNodes");
            List<ConditionNodeConfig> configs = new ArrayList<>();
            if (Validator.isNotEmpty(conditionJsonNodes)){
               if (conditionJsonNodes.isArray()){
                   for (JsonNode conditionJsonNode:conditionJsonNodes){
                       //log.info(conditionJsonNode.toPrettyString());
                       configs.add((ConditionNodeConfig)buildNode(conditionJsonNode.toPrettyString()));
                   }
               }
            }
            nodeConfig.setConditions(configs);
            return nodeConfig;
        }
        return null;
    }
}
